package com.mcp.converter.domain.rule.compatibility.function;

import com.mcp.converter.domain.checker.IncompatibilityDetail;
import com.mcp.converter.shared.response.sql.SQLElement;
import com.mcp.converter.domain.rule.compatibility.AbstractFunctionRule;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 层次查询函数兼容性规则
 * OceanBase中层次查询函数的支持程度和语法与Oracle有差异
 * @author zengxiong
 */
public class HierarchyFunctionRule extends AbstractFunctionRule {

    private static final String RULE_ID = "FN005";
    private static final String RULE_NAME = "层次查询函数差异";
    private static final String RULE_DESCRIPTION = "OceanBase中层次查询函数的支持程度和语法与Oracle存在差异";

    private static final Set<String> HIERARCHY_FUNCTIONS = new HashSet<>(Arrays.asList(
        "CONNECT_BY_ROOT", "PRIOR",
        "LEVEL", "CONNECT_BY_ISLEAF", "CONNECT_BY_ISCYCLE"
    ));

    public HierarchyFunctionRule() {
        super(RULE_ID, RULE_NAME, RULE_DESCRIPTION);
        setIncompatibilityDetail(
            "OceanBase中层次查询函数在以下方面与Oracle存在差异：\n" +
            "1. CONNECT_BY_ROOT：\n" +
            "   - 支持程度有限\n" +
            "   - 可能需要转换为其他表达式\n" +
            "   - 在复杂查询中的行为可能不同\n" +
            "2. PRIOR：\n" +
            "   - 层次查询语法有差异\n" +
            "   - 在复杂条件中的处理不同\n" +
            "   - 与其他操作符的组合使用可能有限制\n" +
            "3. 其他相关函数：\n" +
            "   - LEVEL伪列的实现差异\n" +
            "   - CONNECT_BY_ISLEAF的判断逻辑不同\n" +
            "   - CONNECT_BY_ISCYCLE的循环检测机制差异",
            "可能导致：\n" +
            "1. 层次查询结果不一致\n" +
            "2. 层次关系判断失败\n" +
            "3. 循环检测异常\n" +
            "4. 性能问题",
            "建议：\n" +
            "1. 简化层次查询结构：\n" +
            "   - 避免复杂的层次条件\n" +
            "   - 减少嵌套层级\n" +
            "2. 循环处理：\n" +
            "   - 增加显式的循环检测\n" +
            "   - 限制最大层级数\n" +
            "3. 替代方案：\n" +
            "   - 考虑使用递归CTE\n" +
            "   - 使用应用层处理复杂层次\n" +
            "4. 测试建议：\n" +
            "   - 测试各种层次结构\n" +
            "   - 验证边界条件\n" +
            "   - 检查性能影响",
            IncompatibilityDetail.Severity.HIGH
        );
    }

    @Override
    public boolean matches(Object target) {
        if (target instanceof SQLElement) {
            SQLElement element = (SQLElement) target;
            if (isFunctionElement(element)) {
                String functionName = element.getName().toUpperCase();
                return HIERARCHY_FUNCTIONS.contains(functionName);
            }
        }
        return false;
    }
    
    @Override
    public Set<String> getIncompatibleFunctions() {
        return new HashSet<>(HIERARCHY_FUNCTIONS);
    }
}